# -*- coding: utf-8 -*-
# from odoo import api, fields, models,_
from odoo.exceptions import AccessError, UserError, ValidationError
from passlib.context import CryptContext
import os
import hashlib
import json
import logging
from odoo import api, http, models,fields,_
from odoo.http import request
from odoo.tools import file_open, image_process, ustr
from odoo.tools.misc import str2bool
import re
import odoo.addons.decimal_precision as dp
import logging
_logger = logging.getLogger(__name__)
# import numpy as np
import base64
from odoo.modules.module import get_module_resource
from odoo import tools

# WORKTYPE_SELECTION=[('A1','数值'),('A2','判断'),('A3','输入'),('A4','统计'),('A1M','多扭矩模式'),('A2M','多扭矩+角度模式')]
WORKTYPE_SELECTION=[('A1','数值'),('B2','判断'),('B3','输入'),('C1','照片'),('A4','统计'),('A1M','多扭矩模式'),('A2M','多扭矩+角度模式')]
UNIT_SELECTION=[('mm','mm'),('in','in'),('°C','°C'),('MPa','MPa'),('%','%'),('l','l'),('ml','ml'),('kg','kg'),
                ('g','g'),('datetiem','datetime'),('Nm','Nm'),('ft.lb','ft.lb'),('in.lb','in.lb'),('kg.cm','kg.cm')]
GRP_SELECTION=[('#1','#1'),('#2','#2'),('#3','#3'),('#4','#4'),('#5','#5'),('#6','#6'),
                          ('#7','#7'),('#8','#8'),('#9','#9'),('#10','#10'),('#11','#11'),('#12','#12'),
                          ('#13','#13'),('#14','#14'),('#15','#15'),('#16','#16'),('#17','#17'),('#18','#18'),
                          ('#19','#19'),('#20','#20'),('#21','#21'),('0',' ')]
#继承这个类，增加env_company
# class Http(models.AbstractModel):
#     _inherit = 'ir.http'
#     def session_info(self):
#         user = self.env.user
#         session_uid = request.session.uid
#         version_info = odoo.service.common.exp_version()

#         if session_uid:
#             user_context = dict(self.env['res.users'].context_get())
#             if user_context != request.session.context:
#                 request.session.context = user_context
#         else:
#             user_context = {}

#         IrConfigSudo = self.env['ir.config_parameter'].sudo()
#         max_file_upload_size = int(IrConfigSudo.get_param(
#             'web.max_file_upload_size',
#             default=128 * 1024 * 1024,  # 128MiB
#         ))
#         mods = odoo.conf.server_wide_modules or []
#         if request.db:
#             mods = list(request.registry._init_modules) + mods
#         session_info = {
#             # "proto_id":user.proto_id.id, #dbh 增加的与扳手通讯的协议
#             "env_company":user.company_id.name,#dbh 增加的当前登录用户的公司名 
#             "uid": session_uid,
#             "is_system": user._is_system() if session_uid else False,
#             "is_admin": user._is_admin() if session_uid else False,
#             "user_context": user_context,
#             "db": self.env.cr.dbname,
#             "server_version": version_info.get('server_version'),
#             "server_version_info": version_info.get('server_version_info'),
#             "support_url": "https://www.odoo.com/buy",
#             "name": user.name,
#             "username": user.login,
#             "partner_display_name": user.partner_id.display_name,
#             "company_id": user.company_id.id if session_uid else None,  # YTI TODO: Remove this from the user context
#             "partner_id": user.partner_id.id if session_uid and user.partner_id else None,
#             "web.base.url": IrConfigSudo.get_param('web.base.url', default=''),
#             "active_ids_limit": int(IrConfigSudo.get_param('web.active_ids_limit', default='20000')),
#             'profile_session': request.session.profile_session,
#             'profile_collectors': request.session.profile_collectors,
#             'profile_params': request.session.profile_params,
#             "max_file_upload_size": max_file_upload_size,
#             "home_action_id": user.action_id.id,
#             "cache_hashes": {
#                 "translations": self.env['ir.http'].sudo().get_web_translations_hash(
#                     mods, request.session.context['lang']
#                 ) if session_uid else None,
#             },
#             "currencies": self.sudo().get_currencies(),
#             'bundle_params': {
#                 'lang': request.session.context['lang'],
#             },
#         }
#         if request.session.debug:
#             session_info['bundle_params']['debug'] = request.session.debug
#         if self.env.user.has_group('base.group_user'):
#             # the following is only useful in the context of a webclient bootstrapping
#             # but is still included in some other calls (e.g. '/web/session/authenticate')
#             # to avoid access errors and unnecessary information, it is only included for users
#             # with access to the backend ('internal'-type users)
#             menus = self.env['ir.ui.menu'].load_menus(request.session.debug)
#             ordered_menus = {str(k): v for k, v in menus.items()}
#             menu_json_utf8 = json.dumps(ordered_menus, default=ustr, sort_keys=True).encode()
#             session_info['cache_hashes'].update({
#                 "load_menus": hashlib.sha512(menu_json_utf8).hexdigest()[:64], # sha512/256
#             })
#             session_info.update({
#                 # current_company should be default_company
#                 "user_companies": {
#                     'current_company': user.company_id.id,
#                     'allowed_companies': {
#                         comp.id: {
#                             'id': comp.id,
#                             'name': comp.name,
#                             'sequence': comp.sequence,
#                         } for comp in user.company_ids
#                     },
#                 },
#                 "show_effect": True,
#                 "display_switch_company_menu": user.has_group('base.group_multi_company') and len(user.company_ids) > 1,
#             })
          # dbh todo 
#         return session_info

class Measposition(models.Model):
    _name="meas.position"
    _description="位置信息"
    # _order='seq'
    # _sql_constraints = [
    # ('name_uniq',
    # 'UNIQUE (name)',
    # '位置不能重复!')
    # ]
    name=fields.Char('位置名称')
    remark=fields.Char('位置说明')
    # seq=fields.Integer('位置序号',compute="_compute_name",store=True)
    # company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company.id)

    #这是源码。当在action点击复制时，会自动加上copy,以避免重复
    def copy(self, default=None):
        self.ensure_one()
        default = dict(default or {})
        if ('name' not in default):
            default['name'] = _("%s (copy)", self.name)
        return super(Measposition, self).copy(default)
    @api.constrains('name')
    def _check_name(self):
        characters = ['+','-','*','/','(',')']
        for record in self:
            for character in characters:
                if character in record.name:
                    raise ValidationError(_('名称中不能含有+-*/()'))
                else:
                    continue
                

class Meas(models.Model):
    _name="meas.meas"
    _rec_name="title"
    _descriptioon='机型模版'
    _order="id desc"

    name=fields.Char('机型')
    title=fields.Char('机型模版名称')
    remark=fields.Char('工程说明')
    company_id = fields.Many2one('res.company',string="组织",default=lambda self: self.env.company.id)
    # meas_main_ids = fields.One2many('meas.main','meas_id',string='工序单')
    meas_sub_ids = fields.One2many('meas.meas.sub','meas_id',string='工序单')
    no_sub=fields.Boolean('无工序明细',compute='_compute_no_sub')
    document_data1 = fields.Binary(string='工艺图纸', attachment=True)
    document_fname1 = fields.Char('工艺图纸', index=True)
    document_data2 = fields.Binary(string='工艺卡片', attachment=True)
    document_fname2 = fields.Char('工艺卡片', index=True)
    document_data3 = fields.Binary(string='打包文件', attachment=True)
    document_fname3 = fields.Char('打包文件', index=True)
    # document_data4 = fields.Binary(string='附件4', attachment=True)
    # document_fname4 = fields.Char('附件4名', index=True)
    temp=fields.Selection([('0','通用模板'),('6','六点检测模板'),('4','四点甩挡模板'),('5','五点甩挡模板'),('2','复合计算模板'),('10','任意计算模板'),('3','扭矩系统模版'),('null','')],string='模板',default='null')

    # document_image=fields.Image(string="图片文件",max_width=200,max_height=200)
    # def name_get(self):
    #     result=[]
    #     for record in self:
    #         if record.remark:
    #             remark='-'+record.remark 
    #         else:
    #             remark=''
    #         temp_name = dict(record._fields['temp'].selection)[record.temp]
    #         result.append((record.id, u"%s(%s)%s" % (record.name,temp_name,remark)))
    #     return result
    # 计算公式中的不正确写法处理
    @api.constrains('meas_sub_ids')
    def _check_remark(self):
        if self.temp=='10':
            # characters = ['（', '）']
            positions=[]
            for r in self.meas_sub_ids:
                if r.position_id.name:
                    positions.append(r.position_id.name)
            positions=list(set(positions))
            for r in self.meas_sub_ids:
                if r.remark and r.flag==10:
                # if r.remark :
                    remark=r.remark.strip()
                    # 将remark的变量（即除去()+-*/）转换成数组
                    checks=re.split('[()+\-*/]', remark)
                    remarklist=[]
                    # 当头尾为()时，会产生头尾各一个空字符串，所以去掉
                    for check in checks:
                        if check !='' and not check.isnumeric() :
                            remarklist.append(check)
                    for rmk in remarklist:
                        if rmk not in positions:
                            raise ValidationError(_('请填写正确位置！'))
        elif self.temp=='3':
            if len(self.env['meas.meas.sub'].search([('meas_id','=',self.id)]))>10:
                raise ValidationError(_('扭矩系统，一个工单不能超过10条数据！'))
            for r in self.meas_sub_ids:
                if r.worktype_selection.find('M')<0:
                    raise ValidationError(_('扭矩系统的类型不匹配！'))



                    
    #根据机型、模板、工程说明返回机型模版唯一标识
    @api.onchange('name','temp','remark')
    def _onchange_title(self):
        if self.name and self.temp:
            if self.remark:
                remark='-'+self.remark 
            else:
                remark=''
            temp_name = dict(self._fields['temp'].selection)[self.temp]
            self.title=self.name +'('+temp_name +')'+remark 

    @api.depends("meas_sub_ids")
    def _compute_no_sub(self):
       for r in self:
            r.no_sub= not len(r.meas_sub_ids)                         
    def repeat(self):
        id=self.id or self.env.context.get('active_id')
        meas_sub=self.env['meas.meas.sub'].search([('meas_id','=',id)])
        # if not self.no_sub:
        sequence=max(meas_sub.mapped('sequence'))
        self.env['meas.meas.sub'].search([('sequence','=',sequence),('meas_id','=',id)],limit=1).copy({
            'meas_id':id,
            'sequence':sequence+1})
    #这是源码。当在action点击复制时，会自动加上copy,并且复制所有子数据
    def copy(self, default=None):
        default = dict(default or {})
        #传进来的字典中没有name属性（即界面上未修改name）,则加上copy以区别当前是copy
        #注释下面是为了重新创建name,以避免重复
        if ('name' not in default):
            default['name'] = _("%s (copy)", self.name)
        default['company_id']=self.env.company.id
        subs=self.meas_sub_ids
        sublist=[]
        #copy所有self.meas_sub_ids数据，并将id存入sublist,用于后面创建
        for s in subs:
            sublist.append(s.copy().id)
        default['meas_sub_ids']=sublist    
        return super(Meas, self).copy(default)
    
    # @api.model_create_multi
    # def create(self, vals):
    #     if 'meas_sub_ids' in vals and 'temp' in vals and vals.get('temp')=='3':
    #         meas_sub_ids=vals.get('meas_sub_ids')
    #         if len(meas_sub_ids)>10:
    #             raise ValidationError(_('扭矩系统：一个工单最多只能下发10条！'))
    #     super(Meas, self).create(vals)
    #     pass


    # def write(self, vals):
    #     if 'meas_sub_ids' in vals and 'temp' in vals and vals.get('temp')=='3':
    #         meas_sub_ids=vals.get('meas_sub_ids')
    #         if len(meas_sub_ids)>10:
    #             raise ValidationError(_('扭矩系统：一个工单最多只能下发10条！'))
    #     super(Meas, self).create(vals)
    #     pass

class MeasSub(models.Model):
    _name="meas.meas.sub"
    _description="模板节点"
    _rec_name="number"
    _order="sequence"

    # number = fields.Char('节点',compute="_compute_number")
    number = fields.Char('节点')
    meas_id=fields.Many2one('meas.meas',string='机型',ondelete="restrict",index=True,domain=lambda self:[('company_id','=',self.env.company.id)])
    worktype_selection=fields.Selection(selection=WORKTYPE_SELECTION,string='类型',default='A1')
    position_id=fields.Many2one('meas.position',string='位置')
    position=fields.Char(string='位置代号',compute='_compute_position')
    sequence=fields.Integer(string='顺序号')
    # value_unit=fields.Selection([('mm','mm'),('in','in'),('°C','°C'),('MPa','MPa'),('%','%'),('l','l'),('ml','ml')],default="mm",string='单位',required="1")
    value_unit=fields.Selection(UNIT_SELECTION,default="mm",string='单位',required="1")
    target_value=fields.Float(string="目标值(3)",digits='Meas of Unit')
    min_value=fields.Float(string='下值公差(3)',digits='Meas of Unit')
    max_value=fields.Float(string='上值公差(3)',digits='Meas of Unit')
    # allow=fields.Float(string='误差范围(3):',default=0.000,digits='Meas of Unit')
    target_value2=fields.Float(string="目标值",digits='two of Unit')
    min_value2=fields.Float(string='下值公差',digits='two of Unit')
    max_value2=fields.Float(string='上值公差',digits='two of Unit')
    allow2=fields.Float(string='误差范围:',default=0.00,digits='two of Unit')
    remark=fields.Char("要求(公式)")
    remark_formula=fields.Char("公式")
    operator_id = fields.Many2one('res.users',string='操作员',default=lambda self:self.env.user.id)
    company_id = fields.Many2one('res.company',string="组织",related="meas_id.company_id", store=True)
    # result=fields.Text('自定义输入')
    # check=fields.Boolean('判断检测')
    # worktype_value=fields.Char('导出数据显示值')
    decimal=fields.Boolean('小数点三位',default=False)
    # grp=fields.Selection([('#1','#1'),('#2','#2'),('#3','#3'),('#4','#4'),('#5','#5'),('#6','#6'),
    #                       ('#7','#7'),('#8','#8'),('#9','#9'),('0',' ')],default='#1',string='组')
    grp=fields.Selection(GRP_SELECTION ,default='#1',string='组')
    temp=fields.Selection(string='模版',related="meas_id.temp")
    flag=fields.Integer(string='计算标志位',help='不等于0时,代表计算数据',default=0)
    # target_angle2=fields.Float('角度',digits='two of Unit',default=0)
    min_angle2=fields.Float('最小角度',digits='two of Unit',default=0)
    max_angle2=fields.Float('最大角度',digits='two of Unit',default=0)
    # target_angle=fields.Float('角度(3)',digits='Meas of Unit',default=0)
    min_angle=fields.Float('最小角度(3)',digits='Meas of Unit',default=0)
    max_angle=fields.Float('最大角度(3)',digits='Meas of Unit',default=0)
    ref_image=fields.Image(string="参考图",max_width=200,max_height=200)

# WORKTYPE_SELECTION=[('A1','数值'),('B2','判断'),('B3','输入'),('A4','统计'),('A1M','多扭矩模式'),('A2M','多扭矩+角度模式')]
    @api.onchange('temp')
    def _onchange_temp(self):
        if self.temp=='3':
            self.worktype_selection='A1M'
            self.value_unit='Nm'
        else:
            self.worktype_selection='A1'
            self.value_unit='mm'
    @api.onchange('remark_formula')
    def _compute_remark(self):
        position_obj=self.env['meas.position']
        pat1=re.compile(r'@\d+')
        pat2=re.compile(r'@(\d+)')
        if self.remark_formula:
            #获取所有@+数字的列表
            ms=pat1.findall(self.remark_formula)
            if ms:
                rem=self.remark_formula
                if len(ms)>0:
                    for remk in ms:
                        m=pat2.match(remk) #匹配@+数字
                        id=int(m.group(1)) #取数字部分
                        position=position_obj.browse(int(id)).name
                        rem=rem.replace(m.group(),position.strip()) #m.group()是匹配的字符串
                    self.remark=rem

    @api.depends('position_id')
    def _compute_position(self):
        for r in self:
            if r.position_id:
                r.position='@'+str(r.position_id.id)
            else:
                r.position=''
    @api.onchange('position_id')
    def _onchange_position_id(self):
        if self.position_id:
            self.flag=0
            self.max_value=0.000
            self.max_value2=0.00
        else:
            # 计算数据行
            if self.temp=='null':
                raise ValidationError('须先选择模版')
            self.flag=int(self.temp)
            self.max_value=0.6
            self.max_value2=0.6
            pass
            
    #根据decimal=true,则按三位计算字段，否则按两位计算字段
    @api.onchange('decimal','target_value','target_value2','allow2')
    def _onchange_target_value(self):
        # if self.decimal and self.target_value:
        if self.decimal:
            # if self.worktype_selection.endswith('M'):
            #     self.decimal=False
            #     return
            if self.target_value==0:
                self.min_value=-self.allow2
                self.max_value=self.allow2
            else:
                self.min_value=self.target_value*(1-self.allow2)
                self.max_value=self.target_value*(1+self.allow2)
        # elif not self.decimal and self.target_value2:    
        elif not self.decimal:    
            if self.target_value2==0:
                self.min_value2=-self.allow2
                self.max_value2=self.allow2
            else:
                self.min_value2=self.target_value2*(1-self.allow2)
                self.max_value2=self.target_value2*(1+self.allow2)

    # @api.onchange('worktype_selection')
    # def _onchange_worktype_selection_value(self):
    #     string_value = dict(self._fields['worktype_selection'].selection)
    #     self.worktype_value=string_value.get(self.worktype_selection)

class MeasMain(models.Model):
    _name="meas.main"
    _description="工序模板"
    _rec_name="name"
    _order="name desc,sequence"

    @api.model
    def _default_image(self):
        image_path = get_module_resource('meas', 'static/src/img', 'default_image.png')
        # return tools.image_resize_image_big(base64.b64encode(open(image_path, 'rb').read()))
        return base64.b64encode(open(image_path, 'rb').read())

    name = fields.Char(
        string="工序单号",
        # required=True, copy=False, readonly=True,
        required=True, copy=False,
        index='trigram',
        default=lambda self: _('New')
        )
    title=fields.Char('工序名称')
    require=fields.Text('工艺要求')    
    sequence=fields.Integer('序列号')
    # meas_id=fields.Many2one('meas.meas',string='机型模版',ondelete="restrict",index=True,domain=lambda self:[('company_id','=',self.env.company.id)])
    meas_id=fields.Many2one('meas.meas',string='机型模版',ondelete="restrict",index=True)
    meas_name=fields.Char('机型',related="meas_id.name",store=True)
    datetime_mainship=fields.Datetime('工序单日期',default=fields.Datetime.now())
    main_sub_ids=fields.One2many('meas.main.sub','main_id',string='工序节点')
    company_id = fields.Many2one('res.company',string="组织",default=lambda self: self.env.company.id)
    operator_id = fields.Many2one('res.users', default=lambda self: self.env.user.id)
    dispatch = fields.Boolean('下发了的标识',default=False)
    dispatched = fields.Boolean('曾经下发过的',default=False)
    state = fields.Selection( [('dispatch','下发'),('draft','初稿')], 'State',
                             default='draft')
    no_sub=fields.Boolean('无工序明细',compute='_compute_no_main_sub')
    no_dispatch_sub=fields.Boolean('无下发节点',compute='_compute_no_main_sub')
    to_xls=fields.Boolean('导出文件状态',default=False)
    document_data1 = fields.Binary(string='附件1', attachment=True)
    document_fname1 = fields.Char('附件1名', index=True)
    document_data2 = fields.Binary(string='附件2', attachment=True)
    document_fname2 = fields.Char('附件2名', index=True)
    document_data3 = fields.Binary(string='附件3', attachment=True)
    document_fname3 = fields.Char('附件3名', index=True)
    document_data4 = fields.Binary(string='附件4', attachment=True)
    document_fname4 = fields.Char('附件4名', index=True)
    document_image=fields.Image(string="图片文件")
    document_image2=fields.Image(string="图片文件")
    document_image3=fields.Image(string="图片文件")
    # document_image=fields.Image(string="图片文件",max_width=200,max_height=200)
    ref=fields.Char('工艺卡号')
    prd_id=fields.Many2one('meas.prd','机号')
    prd_num=fields.Char(string='编号',related="prd_id.project",store=True)
    gotit=fields.Boolean('机号已输入',compute="_compute_gotit",store=True)
    # prd_name=fields.Char('机型',related="meas_id.name")
    # tool_id=fields.Many2one('meas.tool.info',string='所用工具',domain=lambda self:[('company_id','=',self.env.company.id)])
    # tool_ids=fields.One2many('meas.tool.info','meas_main_id',string='所用工具')
    tool_ids=fields.Many2many('meas.tool.info',string='所用工具')
    key=fields.Boolean('关键过程否?',default=False)
    key_image=fields.Binary(string="关键标识",attachment=True,default=_default_image)
    permit_user_ids=fields.Many2many('res.users',string="可操作人员")
    have_permit=fields.Boolean('已经选择了允许操作人员',compute="_compute_have_permit",default=False)
    temp=fields.Selection(string='模板',related='meas_id.temp',store=True)
    direction=fields.Selection([('CW','顺时针方向'),('CCW','逆时针方向')],default='CW',string='方向')
    pass_allow=fields.Float('允许误差',digits='Meas of Unit')
    max_temperature=fields.Integer('最大温度°C',default=35)
    max_humidity=fields.Integer('最大湿度%',default=85)


    # 计算公式中的不正确写法处理
    @api.constrains('main_sub_ids')
    def _check_remark(self):
        if self.temp=='10':
            # characters = ['（', '）']
            positions=[]
            for r in self.main_sub_ids:
                if r.position_id.name:
                    positions.append(r.position_id.name)
            positions=list(set(positions))
            for r in self.main_sub_ids:
                if r.remark and r.flag==10:
                # if r.remark :
                    remark=r.remark.strip()
                    # 将remark的变量（即除去()+-*/）转换成数组
                    checks=re.split('[()+\-*/]', remark)
                    remarklist=[]
                    # 当头尾为()时，会产生头尾各一个空字符串，所以去掉
                    for check in checks:
                        if check !='' and not check.isnumeric() :
                            remarklist.append(check)
                    for rmk in remarklist:
                        if rmk not in positions:
                            raise ValidationError(_('请填写正确位置！'))
                    # 处理输入了汉字的()时报错    
                    # for c in characters:
                    #     if c in r.remark:
                    #         raise ValidationError(u'公式中不能含有全角括号！')
                    #     else:
                    #         continue
    #这是源码。当在action点击复制时，会自动加上copy,并且复制所有子数据
    def copy(self, default=None):
        default = dict(default or {})
        #传进来的字典中没有name属性（即界面上未修改name）,则加上copy以区别当前是copy
        #注释下面是为了重新创建name,以避免重复
        # if ('name' not in default):
        #     default['name'] = _("%s (copy)", self.name)
        subs=self.main_sub_ids
        sublist=[]
        #copy所有self.main_sub_ids数据，并将id存入sublist,用于后面创建
        for s in subs:
            sublist.append(s.copy().id)
        default['main_sub_ids']=sublist    
        return super(MeasMain, self).copy(default)
    
    #当复制工序模板后，选择工程单号，自动将工序模板名修改为@机型并且为逆时针时后面加逆
    # 选择机型及机号，自动引入机型模板中的明细数据
    @api.onchange('meas_id','prd_id','direction')
    def _onchange_name(self):
        if self.name and self.meas_id and self.prd_id:
            self.name=self.name.split('@')[0]+'@'+self.meas_id.name+ '-' + self.prd_id.name + ('(逆)' if self.direction=='CCW' else '') 
            self.temp=self.meas_id.temp
            position_list=[]
            # 从机型模板明细创建工序明细数据
            self.main_sub_ids=[(5,0)]
            for s in self.meas_id.meas_sub_ids:
                position_list.append(s.position_id.name)
                self.main_sub_ids.create({
                    'main_id':self.id,
                    'worktype_selection':s.worktype_selection,
                    'position_id':s.position_id.id,
                    'grp':s.grp,
                    'decimal':s.decimal,                   
                    'sequence':s.sequence,
                    'value_unit':s.value_unit,
                    'target_value':s.target_value,
                    'min_value':s.min_value,
                    'max_value':s.max_value,
                    # 'allow':s.allow,
                    'target_value2':s.target_value2,
                    'min_value2':s.min_value2,
                    'max_value2':s.max_value2,
                    'allow2':s.allow2,
                    'min_angle2':s.min_angle2,
                    'max_angle2':s.max_angle2,
                    'min_angle':s.min_angle,
                    'max_angle':s.max_angle,
                    # 'operator_id':s.operator_id.id,
                    # 'company_id':s.company_id.id,
                    'remark':s.remark,
                    'flag':s.flag,
                    'ref_image':s.ref_image  
                })
            seq=max(self.main_sub_ids.mapped('sequence'))
            # delta模板时，需要每组后面加一个空记录
            if self.temp=='2':
                flag=len(self.main_sub_ids)
                #只有处理两个数据时,才需要计算允许误差
                if flag !=2:
                    self.pass_allow=0.00
                else:
                    self.pass_allow=0.600
                grp=self.main_sub_ids[0].grp
                # 需要增加两行
                if flag==4:
                    # remark='|'+position_list[2]+'-'+position_list[0]+'|'
                    remark=position_list[2]+'-'+position_list[0]
                    self.main_sub_ids.create({'main_id':self.id,
                                          'grp':grp,'sequence':seq+1,
                                          'remark':remark,
                                          'flag':flag*10,
                                          'max_value':0.600,
                                          'max_value2':0.60
                                        })    
                    # remark='|'+position_list[1]+'-'+position_list[3]+'/2|'
                    remark=position_list[1]+'-'+position_list[3]+'/2'
                    self.main_sub_ids.create({'main_id':self.id,
                                          'grp':grp,'sequence':seq+2,
                                          'remark':remark,
                                          'flag':flag*10+1,
                                          'max_value':0.600,
                                          'max_value2':0.60
                                          })    
                elif flag==3:
                    # remark='|('+position_list[0]+'+'+position_list[1]+')/2-'+position_list[2]+'|'
                    remark='('+position_list[0]+'+'+position_list[1]+')/2-'+position_list[2]
                    self.main_sub_ids.create({'main_id':self.id,
                                          'grp':grp,'sequence':seq+1,
                                          'remark':remark,
                                          'flag':flag,
                                          'max_value':0.600,
                                          'max_value2':0.60
                                          })    
                else:
                    if flag==2:
                        remark=position_list[0]+'+'+position_list[1]
                    else:
                        remark=''    
                    self.main_sub_ids.create({'main_id':self.id,
                                            'grp':grp,'sequence':seq+1,
                                            'remark':remark,
                                            'flag':flag})    
    @api.onchange('temp')
    def _onchange_direction(self):
        if self.temp=='0':
            self.direction=''

    @api.depends('permit_user_ids')
    def _compute_have_permit(self):
        for r in self:
            r.have_permit=bool(len(r.permit_user_ids))

    #当关键过程变换时，清楚原来所选的量具
    @api.onchange('key')
    def _onchange_key(self):
        self.tool_ids=[(5,)]

   
    @api.depends('prd_id')
    def _compute_gotit(self):
        for r in self:
            if r.prd_id:
                r.gotit=True
            else:
                r.gotit=False
   
    @api.depends("main_sub_ids")
    def _compute_no_main_sub(self):
        for r in self:
            r.no_sub= not len(r.main_sub_ids)                         
            #根据有没有明细，设置state
            if r.no_sub:
                r.state='draft'
            else:
                r.state='dispatch'
            r.no_dispatch_sub = not any(r.main_sub_ids.mapped('dispatch')) 

    @api.model_create_multi
    def create(self, vals_list):
        for vals in vals_list:
            vals['company_id']=self.env.company.id    
            meas_id=vals['meas_id']
            meas_name=self.env['meas.meas'].search([('id','=',meas_id)]).name
            prd_id=vals['prd_id']
            prd_name=self.env['meas.prd'].search([('id','=',prd_id)]).name   
            self = self.with_company(vals['company_id'])
            if vals.get('name', _("New")).startswith(_("New")):
                seq=self.env['ir.sequence'].search([('code','ilike','meas.main'),('company_id','=',vals['company_id'])])
                if not seq:
                    seq=self.env['ir.sequence'].sudo().create({
                        'name':'meas_main',
                        'code':'meas.main.%s' % vals['company_id'],
                        'implementation':'standard',
                        'active':True,
                        'company_id':vals['company_id'],
                        'prefix':'M',
                        'padding':3,
                        'number_increment':1,
                        'suffix':'',
                        'use_date_range':False
                    })
                # title=vals.get('title',False)
                # if not title:
                #     title=''
                # else :
                #     title='-'+title    
                # vals['name'] = seq.next_by_code('meas.main'+ '.'+ str(vals['company_id'])) + title + '@'+ meas_name  or _("New")
                vals['name'] = seq.next_by_code('meas.main'+ '.'+ str(vals['company_id'])) + '@'+ meas_name + '-'+prd_name or _("New")
            # 判断有没有创建明细，设置state    
            if vals.get('main_sub_ids',False):    
                vals['state']='dispatch'    
            else:
                vals['state']='draft'    
        return super().create(vals_list)

    def update_dispatch(self):
        #active_model=meas.main
        active_list=self.env.context.get('active_ids',self.ids)
        active_model=self.env.context.get('active_model',self._name)
        for i in active_list:
            record=self.env[active_model].browse(i)
            if len(record.permit_user_ids.ids)==0 and not record.dispatch:
                display_name=record.display_name                
                raise ValidationError(display_name + ' 未选择可操作人员!')
        #将所有已经下发的部分设置到dispatched,然后还原dispatch=false
        records=self.env[active_model].search([('dispatch','=',True)])
        active_records=self.env[active_model].search([('id','in',active_list)])
        #保存目前已下发的至dispatched
        for r in records:
            r.dispatched=r.dispatch
            for w in r.main_sub_ids:
                w.dispatched=r.dispatch
        #设置dispatch        
        for r in active_records:
            #当不可下发时并且还未下发，就跳过
            if not r.gotit and not r.dispatch:
                raise ValidationError(r.display_name + ' 未确定机号及工程编号！')
            if r.dispatch: #只有管理员可以取消下发，
                if self.env.user.has_group('meas.group_meas_manager'):
                    r.dispatch=not r.dispatch
                    for w in r.main_sub_ids:
                        w.dispatch=r.dispatch  #工单明细跟着工单的设置
                else:
                    raise ValidationError('非管理员不能取消下发！取消下发会引起移动端数据混乱')
                    
            else:
                r.dispatch=not r.dispatch
                for w in r.main_sub_ids:
                    #当不可下发时并且还未下发，就跳过
                    # if not w.gotit:
                    #     continue
                    w.dispatch=r.dispatch  #工单明细跟着工单的设置
        # self.update_meas_work(company_id,active_list)
        self.update_meas_work(active_list)
        # for r in active_records:
        #     if r.dispatch:
        #         self.action_permit_users()
        return
    #保证未下发时要将工单中移除，下发的要在工单中创建。即下发与不下发的设置同步处理工单内容    
    # def update_meas_work(self,company_id,active_list):
    def update_meas_work(self,active_list):
        # company_id=self.env.company.id
        # meas_work_sub_list=self.env['meas.work.sub'].search([('company_id','=',company_id)]).mapped('meas_main_sub_id.id')
        # meas_main_sub=self.env['meas.main.sub'].search([('gotit','=',True),('dispatch','=',True),('company_id','=',company_id)])
        # for r in meas_main_sub:
        #     #只当工单中没有的创建
        #     if r.id not in meas_work_sub_list:
        #         self.env['meas.work.sub'].create({
        #             'meas_main_sub_id':r.id
        #             })
        meas_main=self.env['meas.main'].browse(active_list)
        meas_work_main_list=self.env['meas.work.main'].search([]).mapped('main_id.id')
        # meas_main=self.env['meas.main'].search([('gotit','=',True),('dispatch','=',True)])
        for r in meas_main:
            #只当工单中没有的创建
            if r.id not in meas_work_main_list:
            #创建meas.work.main,其中的main_id设为meas.main的id,将当前环境的company_id设为工单的company_id
                work_main=self.env['meas.work.main'].sudo().create({
                    'main_id':r.id,
                    # 'company_id':company_id,
                    # 'permit_user_ids':r.permit_user_ids
                    })
                #创建meas.work.sub,其中的meas_main_sub_id设为meas.main.sub的id
                for rec in self.env['meas.main.sub'].search([('main_id','=',r.id)]):
                    self.env['meas.work.sub'].sudo().create({'meas_main_sub_id':rec.id,'work_main_id':work_main.id})
                  
        #将取消下发的工单删除        
        # meas_main_sub_id_list=self.env['meas.main.sub'].search([('dispatch','=',False)]).mapped('id')
        # to_unlink_work_sub=self.env['meas.work.sub'].sudo().search([('meas_main_sub_id','in',meas_main_sub_id_list)])
        # if len(to_unlink_work_sub)!=0:
        #     to_unlink_work_sub.unlink()
        # meas_main_id_list=self.env['meas.main'].search([('dispatch','=',False),('company_id','=',company_id)]).mapped('id')
        meas_main_id_list=meas_main.search([('id','in',active_list),('dispatch','=',False)]).ids
        to_unlink_work_main=self.env['meas.work.main'].search([('main_id','in',meas_main_id_list)])
        if len(to_unlink_work_main)!=0:
            to_unlink_work_main.work_sub_ids.sudo().unlink()
            to_unlink_work_main.sudo().unlink()
            # to_unlink_work_main.work_sub_ids.search([('work_main_id','=',False)]).sudo().unlink()
        # self.permit_user_ids=[(5,)]    
        return    

    # def to_excel(self):
    #     action = {
    #             'name': '导出xlsx',
    #             'res_model': 'meas.main.sub',
    #             'report_type':'xlsx',
    #             'type': 'ir.actions.report',
    #             "report_name":"meas.report_meas_main_sub_xlsx",
    #             "report_file":"meas.report_meas_main_sub_xlsx" 
    #         }
    #     self.to_xls=False
        # return action
    def action_permit_users(self):
        action = {
                'name': '选择可操作人员员',
                'res_model': 'meas.permit.users.wizard',
                'type': 'ir.actions.act_window',
                'view_mode': 'form',
                # 'views': [[self.env.ref('permit_users_wizard_form').id, 'form']],
                 'views': [(False, 'form')],
                'target': 'new',
            }
        return action    
    def repeat(self):
        id=self.id or self.env.context.get('active_id')
        #重复#1组的数据,并添加在最后以及组号自动增加
        main_sub=self.env['meas.main.sub'].search([('main_id','=',id),('grp','=','#1')])
        #去除重复后的grp列表
        grps=list(set(self.env['meas.main.sub'].search([('main_id','=',id)]).mapped('grp')))
        grplst=[]
        for g in grps:
            grplst.append(int(g[1:]))
        #添加数据的组号
        grp=max(grplst)+1
        #当前最大的sequence
        sequence=max(self.env['meas.main.sub'].search([]).mapped('sequence'))
        if len(main_sub)!=0:
            for m in main_sub:
                sequence=sequence+1
                m.copy({'main_id':id,'grp':'#'+str(grp),'sequence':sequence})
    def choose_repeat(self):
        id=self.id or self.env.context.get('active_id')
        main_sub=self.env['meas.main.sub'].search([('main_id','=',id),('choose','=',True)])
        #当前最大的sequence
        sequence=max(self.env['meas.main.sub'].search([]).mapped('sequence'))
        if len(main_sub)!=0:
            for m in main_sub:
                sequence=sequence+1
                m.copy({'main_id':id,'sequence':sequence})
        main_sub.update({'choose':False})
    #获取机号及工程编号：            
    def getprd(self):
        active_ids=self.env.context.get('active_ids')
        if len(active_ids)!=0:
            # for active_id in active_ids:
            #     meas_meas=self.env['meas.main'].search([('id','=',active_id)]).meas_id.display_name
            action = {
                    'name': '设置机号及工程编号',
                    'res_model': 'meas.prd.wizard',
                    'type': 'ir.actions.act_window',
                    'view_mode': 'form',
                    'views': [[self.env.ref('meas.get_prd_form_wizard').id, 'form']],
                    'target': 'new'
                }
            return action    
    
class MeasMainSub(models.Model):
    _name="meas.main.sub"
    _description="工序节点"
    _rec_name="number"
    _order="sequence"

    # number = fields.Char('节点',compute="_compute_number",store=True)
    number = fields.Char('节点',compute="_compute_number")
    main_id=fields.Many2one('meas.main',string='工序单号',ondelete="restrict",index=True,domain=lambda self:[('company_id','=',self.env.company.id)])
    # meas_id=fields.Many2one('meas.meas',string='工程单号',ondelete="restrict",index=True,related='main_id.meas_id')
    worktype_selection=fields.Selection(selection=WORKTYPE_SELECTION,string='类型',default='A1')
    # position_id=fields.Many2one('meas.position',string='位置',domain=lambda self:[('company_id','=',self.env.company.id)])
    position_id=fields.Many2one('meas.position',string='位置')
    sequence=fields.Integer(string='顺序号')
    value_unit=fields.Selection(UNIT_SELECTION,default="mm",string='单位',required="1")
    target_value=fields.Float(string="目标值(3)",digits='Meas of Unit')
    min_value=fields.Float(string='下值公差(3)',digits='Meas of Unit')
    max_value=fields.Float(string='上值公差(3)',digits='Meas of Unit')
    # allow=fields.Float(string='误差范围(3):',default=0.000,digits='Meas of Unit')
    target_value2=fields.Float(string="目标值",digits='two of Unit')
    min_value2=fields.Float(string='下值公差',digits='two of Unit')
    max_value2=fields.Float(string='上值公差',digits='two of Unit')
    allow2=fields.Float(string='误差范围:',default=0.00,digits='two of Unit')
    remark=fields.Char("要求(公式)")
    dispatch = fields.Boolean('可下发的工单')
    dispatched = fields.Boolean('已经下发的工单')
    operator_id = fields.Many2one('res.users',string='操作员',default=lambda self:self.env.user.id)
    company_id = fields.Many2one('res.company',string="组织",related="main_id.company_id", store=True)
    # result=fields.Text('自定义输入')
    # check=fields.Boolean('判断检测')
    # real_value=fields.Float('实测数据(3位)',digits="Meas of Unit")
    # real_value2=fields.Float('实测数据(2位)',digits="two of Unit")
    # worktype_value=fields.Char('导出数据显示值')
    decimal=fields.Boolean('小数点三位',default=False)
    gotit=fields.Boolean(string='机号已输入',related="main_id.gotit",store=True)
    grp=fields.Selection(GRP_SELECTION,default='#1',string='组')
    flag=fields.Integer(string='标志位',help='获取delta模板中需要参与计算即需要采集数据的个数，以便区别不同计算公式处理数据')
    choose=fields.Boolean(string='选中',default=False)
    # target_angle2=fields.Float('角度',digits='two of Unit',default=0)
    min_angle2=fields.Float('最小角度',digits='two of Unit',default=0)
    max_angle2=fields.Float('最大角度',digits='two of Unit',default=0)
    # target_angle=fields.Float('角度(3)',digits='Meas of Unit',default=0)
    min_angle=fields.Float('最小角度(3)',digits='Meas of Unit',default=0)
    max_angle=fields.Float('最大角度(3)',digits='Meas of Unit',default=0)
    ref_image=fields.Image(string="参考图",max_width=200,max_height=200)

    #当选择扭矩时，设置单位及精度为2位 
    @api.onchange('worktype_selection')
    def _onchange_worktype_selection(self):
        if self.worktype_selection.endswith('M'):
            # self.decimal=False
            self.value_unit='Nm'
        else:
            self.value_unit='mm'
    @api.depends('main_id','position_id','grp')
    def _compute_number(self):
        for r in self:
            if r.grp=='0':
                r.number="%s%s@%s" % ('',r.position_id.name,r.main_id.name)    
            else:
                r.number="%s%s@%s" % (r.grp,r.position_id.name,r.main_id.name)    
            
    #根据decimal=true,则按三位计算字段，否则按两位计算字段
    @api.onchange('decimal','target_value','target_value2','allow2')
    def _onchange_target_value(self):
        # if self.decimal and self.target_value:
        if self.decimal:
            # if self.worktype_selection.endswith('M'):
            #     self.decimal=False
            #     return
            if self.target_value==0:
                self.min_value=-self.allow2
                self.max_value=self.allow2
            else:
                self.min_value=self.target_value*(1-self.allow2)
                self.max_value=self.target_value*(1+self.allow2)
        # elif not self.decimal and self.target_value2:    
        elif not self.decimal:    
            if self.target_value2==0:
                self.min_value2=-self.allow2
                self.max_value2=self.allow2
            else:
                self.min_value2=self.target_value2*(1-self.allow2)
                self.max_value2=self.target_value2*(1+self.allow2)

    # @api.onchange('worktype_selection')
    # def _onchange_worktype_selection_value(self):
    #     string_value = dict(self._fields['worktype_selection'].selection)
    #     self.worktype_value=string_value.get(self.worktype_selection)


class MeasData(models.Model):
    _name="meas.data"
    _description="自检表数据"
    _rec_name="meas_main_sub_id"
    _order="meas_main_id,sequence,datetime_work"

    sequence=fields.Integer(string='顺序号',related="meas_main_sub_id.sequence",store=True)
    meas_main_sub_id=fields.Many2one('meas.main.sub',string="工序明细")
    meas_main_id=fields.Many2one('meas.main',string='工序单号')
    number = fields.Char('节点号',related="meas_main_sub_id.number")
    worktype_selection=fields.Selection(string='类型',related="meas_main_sub_id.worktype_selection",store=True)
    position_id=fields.Many2one('meas.position',string='位置',related="meas_main_sub_id.position_id",store=True)
    target_value=fields.Float(string="目标值(3)",digits='Meas of Unit',related="meas_main_sub_id.target_value")
    value_unit=fields.Selection(string='单位',related="meas_main_sub_id.value_unit")
    min_value=fields.Float(string='下值公差(3)',digits='Meas of Unit',related="meas_main_sub_id.min_value")
    max_value=fields.Float(string='上值公差(3)',digits='Meas of Unit',related="meas_main_sub_id.max_value")
    # allow=fields.Float(string='误差范围(3):',digits='Meas of Unit',related="meas_main_sub_id.allow")
    target_value2=fields.Float(string="目标值",digits='two of Unit',related="meas_main_sub_id.target_value2")
    min_value2=fields.Float(string='下值公差',digits='two of Unit',related="meas_main_sub_id.min_value2")
    max_value2=fields.Float(string='上值公差',digits='two of Unit',related="meas_main_sub_id.max_value2")
    allow2=fields.Float(string='误差范围:',default=0.05,digits='two of Unit',related="meas_main_sub_id.allow2")
    remark=fields.Char("说明",related="meas_main_sub_id.remark")
    operator_id = fields.Many2one('res.users',string='操作员')
    company_id = fields.Many2one('res.company',string="组织")
    result=fields.Text('自定义输入')
    check=fields.Boolean('判断检测')
    real_value=fields.Float('实测数据(3)',digits="Meas of Unit")
    real_value2=fields.Float('实测数据',digits="two of Unit")
    # tool_ids=fields.Many2many('meas.tool.info',string='所用工具')
    # worktype_value=fields.Char('导出数据显示值',related="meas_main_sub_id.worktype_value")
    # require=fields.Text('工艺要求',related="meas_main_sub_id.require")
    require=fields.Text('工艺要求',related="meas_main_id.require")
    ref=fields.Char('工艺卡号',related="meas_main_id.ref",store=True)
    # document_image=fields.Image(string="图片文件",max_width=200,max_height=200,related='meas_main_sub_id.document_image')
    document_image=fields.Image(string="图片文件",related='meas_main_id.document_image')
    document_image2=fields.Image(string="图片文件",related='meas_main_id.document_image2')
    document_image3=fields.Image(string="图片文件",related='meas_main_id.document_image3')
    # meas_id=fields.Many2one('meas.meas',string='工程单号',related='meas_main_sub_id.meas_id')
    meas_id=fields.Many2one('meas.meas',string='机型模版',related='meas_main_id.meas_id',store=True)
    meas_name=fields.Char(string='机型',related='meas_main_id.meas_id.name',store=True)
    # prd_name=fields.Char('机型',related="meas_main_sub_id.prd_name",store=True)
    # prd_name=fields.Char('机型',related="meas_main_id.prd_name",store=True)
    datetime_work=fields.Datetime('操作时间')
    # prd_id=fields.Many2one('meas.prd',string='机号',related="meas_main_sub_id.prd_id",store=True)
    prd_id=fields.Many2one('meas.prd',string='机号',related="meas_main_id.prd_id",store=True)
    # prd_num=fields.Char(string='工程编号',related="meas_main_sub_id.prd_num",store=True)
    prd_num=fields.Char(string='工程编号',related="meas_main_id.prd_num",store=True)
    decimal=fields.Boolean(string='小数点三位',related="meas_main_sub_id.decimal",store=True)
    # no_pass=fields.Boolean('未通过',compute="_compute_no_pass",store=True)
    no_pass=fields.Boolean('未通过')
    grp=fields.Selection(string='组',related="meas_main_sub_id.grp",store=True)
    # key=fields.Boolean('关键标识',related="meas_main_sub_id.key",store=True)
    key=fields.Boolean('关键标识',related="meas_main_id.key",store=True)
    key_image=fields.Binary(string="关键标识图",attachment=True,related="meas_main_id.key_image")
    # no_tools=fields.Boolean('未选量具',compute="_compute_no_tools")
    direction=fields.Selection(string='方向',related="meas_main_id.direction",store=True )
    permit_user_ids=fields.Many2many('res.users',string='允许可操作人员',related="meas_main_id.permit_user_ids")
    # target_angle2=fields.Float('角度',digits='two of Unit',related="meas_main_sub_id.target_angle2")
    min_angle2=fields.Float('最小角度',digits='two of Unit',related="meas_main_sub_id.min_angle2")
    max_angle2=fields.Float('最大角度',digits='two of Unit',related="meas_main_sub_id.max_angle2")
    # target_angle=fields.Float('角度(3)',digits='Meas of Unit',related="meas_main_sub_id.max_angle")
    min_angle=fields.Float('最小角度(3)',digits='Meas of Unit',related="meas_main_sub_id.max_angle")
    max_angle=fields.Float('最大角度(3)',digits='Meas of Unit',related="meas_main_sub_id.max_angle")

    signature=fields.Image(string="签字")
    photo=fields.Image(string="照片")
    deviceId=fields.Char('蓝牙设备的ID')
    tool_id=fields.Many2one('meas.tool.info',string='所用工具',compute="_compute_tool")
    temp=fields.Selection('模板',related="meas_main_id.temp",store=True)
    pass_allow=fields.Float('允许误差',digits='Meas of Unit',related="meas_main_id.pass_allow")
    check_value=fields.Float('复测数据(3位)',digits="Meas of Unit")
    check_value2=fields.Float('复测数据(2位)',digits="two of Unit")
    dv=fields.Float('实际误差dv',digits="Meas of Unit")
    dh=fields.Float('实际误差dh',digits="Meas of Unit")
    pass_flag=fields.Boolean('实际甩挡差之差',default=False)
    max_temperature=fields.Integer('最大温度°C',related="meas_main_id.max_temperature")
    max_humidity=fields.Integer('最大湿度%',related="meas_main_id.max_humidity")
    real_temperature=fields.Integer('实际温度°C')
    real_humidity=fields.Integer('实际湿度%')
    flag=fields.Integer(string='计算标志位',related="meas_main_sub_id.flag")
    real_angle2=fields.Float('角度',digits='two of Unit')
    real_angle=fields.Float('角度(3)',digits='Meas of Unit')

    @api.depends('deviceId')
    def _compute_tool(self):
        for r in self:
            if r.deviceId:
                tool_id=self.env['meas.tool.info'].search([('deviceId','=',r.deviceId)])
                if tool_id:
                    r.tool_id=tool_id.id
                else:
                    r.tool_id=self.env['meas.tool.info'].sudo().create({
                        "deviceId":r.deviceId,
                        "partno":r.deviceId
                    }).id
            else:
                r.tool_id=None        

    @api.model_create_multi
    def create(self, vals_list):
        #解决json不能直接传二进制文件的还原，移动端上传已经处理了，所以注释
        # for u in vals_list:
            # if u.get('signature',False):
            #     u['signature']=base64.b64decode((u['signature']).encode('utf-8'))
            # if u.get('photo',False):
            #     u['photo']=base64.b64decode((u['photo']).encode('utf-8'))
        nr=super(MeasData,self.sudo()).create(vals_list)
        for v in vals_list:
            #上传数据后（创建了数据），将工序已下发标识设成未下发并在工单中相应的数据删除
            meas_main=self.env['meas.main'].browse(v['meas_main_id'])
            meas_main.sudo().update({'dispatch':False})
            meas_main.sudo().main_sub_ids.update({'dispatch':False})
            #删除已上传的工单
            self.env['meas.work.main'].sudo().search([('main_id','=',v['meas_main_id'])]).unlink()
        return nr #这个必须要写，否则jsonrpc api 会报错
    
class ToolInfo(models.Model):
    _name="meas.tool.info"
    _description='工具信息'
    # _sql_constraints = [
    # ('deviceId_uniq',
    # 'UNIQUE (deviceId,company_id)',
    # '量具ID不能重复!')
    # ]

    deviceId=fields.Char('量具ID')
    name=fields.Char('量具名称')
    partno=fields.Char('量具型号')
    # company_id = fields.Many2one('res.company',string="组织",ondelete="restrict",default=lambda self:self.env.company.id)
    proto= fields.Selection([('ariter','Ariter'),('bluetork','bluetork')],default='',string="通讯协议")
    key=fields.Boolean('关键标识')
    barcode=fields.Char('二维码',compute="_compute_toolbarcode")

    @api.depends('name','deviceId','partno','key')
    def _compute_toolbarcode(self):
        for r in self:
            # barcode={'id':str(r.id),'name':r.name,'deviceId':r.deviceId,'partno':r.partno,'key':r.key,'company_id':str(r.company_id.id)}
            barcode={'id':str(r.id),'key':r.key}
            r.barcode=json.dumps(barcode)                                           
    #这是源码。当在action点击复制时，会自动加上copy,以避免重复
    def copy(self, default=None):
        self.ensure_one()
        default = dict(default or {})
        if ('partno' not in default):
            default['partno'] = _("%s (copy)", self.partno)
        return super(ToolInfo, self).copy(default)

    def name_get(self):
        rec=[]
        for r in self:
            rec.append((r.id,'%s%s' % (r.name or '',r.partno and '('+r.partno+')' or '')))
            # rec.append((r.id,'%s%s' % (r.partno , ' ('+r.deviceId+')')))
        return rec    

class MeasPrd(models.Model):
    _name="meas.prd"
    _description="产品信息" 

    name=fields.Char('机号')
    project=fields.Char('工程编号')
    company_id = fields.Many2one('res.company',string="组织",default=lambda self: self.env.company.id)


# class MeasItem(models.Model):
#     _name="meas.item"
#     _description="节点"
#     _sql_constraints = [
#     ('name_uniq',
#     'UNIQUE (name)',
#     '节点不能重复!')
#     ]

#     name=fields.Char('节点')
#     remark=fields.Text('详细说明')
#     company_id = fields.Many2one('res.company',string="组织",ondelete="restrict",default=lambda self:self.env.company.id)